package org.vaadinpa.gui.views;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.vaadinpa.Conf;
import org.vaadinpa.data.Fleet;
import org.vaadinpa.data.Planet;
import org.vaadinpa.data.Resource;
import org.vaadinpa.data.Ship;
import org.vaadinpa.exceptions.NotEnoughFundsException;
import org.vaadinpa.gui.VaadinPA;
import org.vaadinpa.gui.ViewWithCommands;
import org.vaadinpa.gui.util.NotificationUtil;
import org.vaadinpa.logic.Command;
import org.vaadinpa.logic.CommandHandler;
import org.vaadinpa.logic.commands.ShipBuildCommand;

import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Component;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.TextField;
import com.vaadin.ui.themes.Reindeer;

public class ShipView extends ViewWithCommands {

	private static final long serialVersionUID = -2019800056964448007L;

	private GridLayout grid = new GridLayout(16, 1);

	private Map<Ship, TextField> shipToNumField = new HashMap<Ship, TextField>();
	private Map<Ship, Button> shipToOrderButton = new HashMap<Ship, Button>();
	private Map<Ship, Label> shipToNumLabel = new HashMap<Ship, Label>();

	public ShipView() {
		grid.addStyleName(Reindeer.LAYOUT_BLACK);
		addComponent(grid);
		setSizeFull();

		grid.removeAllComponents();
		grid.setSizeUndefined();
		grid.setWidth("100%");
		grid.setSpacing(true);
		grid.setMargin(true, false, false, false);

		List<Ship> ships = Ship.getAvailableShips();

		Label name = new Label("Name");
		name.setStyleName("ship-header");
		grid.addComponent(name);
		Label clazz = new Label("Type");
		clazz.setStyleName("ship-header");
		grid.addComponent(clazz);
		Label init = new Label("Init");
		init.setStyleName("ship-header");
		grid.addComponent(init);
		Label time = new Label("Time");
		time.setStyleName("ship-header");
		grid.addComponent(time);
		Label t1 = new Label("T1 type");
		t1.setStyleName("ship-header");
		grid.addComponent(t1);
		Label t2 = new Label("T2 type");
		t2.setStyleName("ship-header");
		grid.addComponent(t2);
		Label power = new Label("Power");
		power.setStyleName("ship-header");
		grid.addComponent(power);
		Label armor = new Label("Armor");
		armor.setStyleName("ship-header");
		grid.addComponent(armor);

		Label powerRatio = new Label("P/C");
		powerRatio.setStyleName("ship-header");
		grid.addComponent(powerRatio);
		Label armorRatio = new Label("A/C");
		armorRatio.setStyleName("ship-header");
		grid.addComponent(armorRatio);

		Label cmetal = new Label("M");
		cmetal.setStyleName("ship-header");
		grid.addComponent(cmetal);
		Label ccrystal = new Label("C");
		ccrystal.setStyleName("ship-header");
		grid.addComponent(ccrystal);
		Label cgold = new Label("G");
		cgold.setStyleName("ship-header");
		grid.addComponent(cgold);
		Label num = new Label("num");
		num.setStyleName("ship-header");
		grid.addComponent(num);

		grid.addComponent(new Label(""));
		grid.addComponent(new Label(""));

		for (Ship s : ships) {
			name = new Label(s.getName());
			grid.addComponent(name);
			clazz = new Label(s.getType().toString());
			grid.addComponent(clazz);
			init = new Label(s.getInit() + "");
			grid.addComponent(init);
			time = new Label(Conf.ETA_SHIP_BUILD[s.getType().ordinal()] + "");
			grid.addComponent(time);
			t1 = new Label(s.getPrimaryTarget().toString());
			grid.addComponent(t1);
			t2 = new Label(s.getSecondaryTarget() == null ? "" : s.getSecondaryTarget().toString());
			grid.addComponent(t2);
			powerRatio = new Label(s.getPower() + "");
			grid.addComponent(powerRatio);
			armorRatio = new Label(s.getArmor() + "");
			grid.addComponent(armorRatio);

			powerRatio = new Label(s.getPowerToCost());
			grid.addComponent(powerRatio);
			armorRatio = new Label(s.getArmorToCost());
			grid.addComponent(armorRatio);

			for (Resource r : Resource.valuesWithoutNew()) {
				cmetal = new Label(s.getPrice(r) + "");
				grid.addComponent(cmetal);
			}

			int total = 0;
			Planet p = VaadinPA.getPlanet();
			for (Fleet f : p.fleets) {
				total += f.get(s);
			}
			total += p.homeFleet.get(s);
			num = new Label(total + "");
			grid.addComponent(num);
			shipToNumLabel.put(s, num);

			TextField orderNum = new TextField();
			orderNum.setValue(0);
			orderNum.setData(s);
			grid.addComponent(orderNum);
			shipToNumField.put(s, orderNum);

			Button order = new Button("Order");
			order.setData(orderNum);
			order.addListener(new BuildListener());

			if (p.level.ordinal() < s.getType().ordinal()) {
				order.setEnabled(false);
			}
			grid.addComponent(order);
			shipToOrderButton.put(s, order);

		}

		java.util.Iterator<Component> it = grid.getComponentIterator();
		while (it.hasNext()) {
			Component c = it.next();
			if (c instanceof Label) {
				c.setSizeUndefined();
			}
		}
	}

	@Override
	public void reload() {

		super.reload();

		List<Ship> ships = Ship.getAvailableShips();

		for (Ship s : ships) {

			int total = 0;
			Planet p = VaadinPA.getPlanet();
			for (Fleet f : p.fleets) {
				total += f.get(s);
			}
			total += p.homeFleet.get(s);
			shipToNumLabel.get(s).setValue(total + "");

			boolean enabled = p.level.ordinal() >= s.getType().ordinal();
			shipToNumField.get(s).setEnabled(enabled);
			shipToOrderButton.get(s).setEnabled(enabled);

		}

	}

	@SuppressWarnings("unchecked")
	@Override
	protected List<? extends Command> getCommands() {
		return CommandHandler.getEvents(ShipBuildCommand.class);
	}

	private class BuildListener implements ClickListener {

		private static final long serialVersionUID = -6212544925530653401L;

		public void buttonClick(ClickEvent event) {
			TextField orderNum = (TextField) event.getButton().getData();
			Ship s = (Ship) orderNum.getData();

			try {
				int maxShips = Integer.MAX_VALUE;
				for (Resource r : Resource.valuesWithoutNew()) {
					int maxFromThisResource = VaadinPA.getPlanet().getFunds(r) / s.getPrice(r);
					if (maxFromThisResource < maxShips) {
						maxShips = maxFromThisResource;
					}
				}
				int num = new Integer(orderNum.getValue().toString()).intValue();

				if (num > maxShips) {
					num = maxShips;
				}

				if (num > 0) {
					ShipBuildCommand c = new ShipBuildCommand(VaadinPA.getPlanet(), s, num);
					CommandHandler.handle(c);
				}

			} catch (NumberFormatException e) {
			} catch (NotEnoughFundsException e) {
				NotificationUtil.warn("", "Not enough resources");
			}

			orderNum.setValue(0);
			reload();

		}
	}

	@Override
	public String getTitle() {
		return "Ship construction";
	}
}
